<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------

namespace app\api\controller\v1;

use app\api\controller\Basic;
use app\common\model\MemberWechatTpl;
use app\common\model\User;
use buwang\facade\WechatMp;
use buwang\facade\WechatProgram;
use buwang\facade\SmsFacade;
use buwang\service\UserService;
use buwang\validate\Miniapp;
use app\common\model\Sms;
use filter\Inspect;
use think\App;

class MiniProgram extends Basic
{

    // 初始化
    protected function initialize()
    {
        parent::initialize();
        $this->scopes = 'mini_program';
    }

    /**
     * 小程序登录接口
     * @return void
     */
    public function login()
    {
        return self::miniappLogin();
    }

    /**
     * 检查应用是否登录
     * @return void
     */
    public function checkLogin()
    {
        if ($this->user) {
            return $this->success('已登录');
        } else {
            return $this->code(401)->error('未登录');
        }
    }

    /**
     * 读取小程序配置
     * @return void
     */
    public function config()
    {
        $wxconfig = [
            'app_name' => $this->bwapp->appname,
            'app_id' => $this->bwapp->id,
            'service_id' => $this->bwapp->service_id,
            'navbar_color' => $this->bwapp->navbar_color ? $this->bwapp->navbar_color : '#ffffff',
            'navbar_style' => $this->bwapp->navbar_style ? $this->bwapp->navbar_style : '#000000',
        ];
        $tpl = MemberWechatTpl::getConfig($this->app_id);
        if ($tpl) {
            $wxconfig['tplmsg'][] = $tpl->tplmsg_common_app;
        }
        return $this->success('应用配置', $wxconfig);
    }


    /**
     * 通过小程序绑定公众号帐号
     * @param [type] $ids
     * @return void
     */
    public function bindOfficial()
    {
        $code = $this->request->param('code');
        self::apiAuth();
        $official = WechatMp::isTypes($this->app_id);//得到公众号操作实例
        if (empty($official)) {
            return view('/bind_official_error');
        }
        if (empty($code)) {
            $response = $official->oauth->scopes(['snsapi_base'])->redirect((string)url('api/v1/bindOfficial', ['service_id' => $this->bwapp['service_id']], false, true));
            return $response->send();
        } else {
            $view['openid'] = $official->oauth->user()->getID();
            $view['service_id'] = $this->bwapp['service_id'];
            return view('/bind_official')->assign($view);
        }
    }

    /**
     * 绑定小程序端获取到的手机号
     * bindWechatMobile
     * @return void
     */
    public function bindWechatMobile()
    {
        $this->isUserAuth();
        if (request()->isPost()) {
            $param = [];
            $param['errMsg'] = $this->request->param('errMsg', 'getPhoneNumber:fail');
            $param['encryptedData'] = $this->request->param('encryptedData');
            $param['iv'] = $this->request->param('iv');
            $param['sign'] = $this->request->param('sign');
            $result = $this->apiSignCheck($param);
            if ($result['code'] = 200) {

                $decryptedData = WechatProgram::isTypes($this->app_id)->encryptor->decryptData($this->user->session_key, $param['iv'], $param['encryptedData']);

                if (!empty($decryptedData['purePhoneNumber'])) {
                    $mobile = $decryptedData['purePhoneNumber'];
                    if ($this->user->mobile == $mobile) {
                        return $this->error('手机号相同不用更换', [], 204);
                    }
                    $rel = User::where(['member_miniapp_id' => $this->app_id, 'mobile' => $mobile])->field('id')->count();
                    if ($rel) {
                        return $this->error('手机号已被占用', [], 204);
                    }
                    //验证通过
                    $res = User::where(['id' => $this->user->id])->update(['mobile' => $mobile]);
                    if ($res) {
                        return $this->success('手机号绑定成功', ['mobile' => $mobile]);
                    }
                    return $this->error('手机号绑定失败', [], 204);
                } else {
                    return $this->error('获取授权信息失败', [], 204);
                }

            } else {
                return $this->code($result['code'])->error($result['msg']);
            }
        } else {
            return $this->code(403)->error('非法请求');
        }
    }

    /**
     * 获取绑定手机验证码
     * @return void
     */
    public function getMobileSms()
    {
        $this->isUserAuth();
        if (request()->isPost()) {
            $param = [];
            $param['errMsg'] = $this->request->param('errMsg', 'getPhoneNumber:fail');
            $param['encryptedData'] = $this->request->param('encryptedData');
            $param['iv'] = $this->request->param('iv');
            $param['sign'] = $this->request->param('sign');
            $result = $this->apiSignCheck($param);
            if ($result['code'] != 200) {
                return $this->code($result['code'])->error($result['msg']);
            }
            $decryptedData = WechatProgram::isTypes($this->app_id)->encryptor->decryptData($this->user->session_key, $param['iv'], $param['encryptedData']);
            if (!empty($decryptedData['purePhoneNumber'])) {
                $mobile = $decryptedData['purePhoneNumber'];
                if ($this->user->mobile != $mobile) {
                    return $this->code(403)->error('手机号验证失败');
                }
                $data['mobile'] = $this->user->mobile;
                $data['code'] = get_num_code(6);//获取6位数字
                //设置验证码 session
                SmsFacade::setSms($data);
                return $this->success('验证成功', ['session_id' => get_session_id(), 'sms' => $data['code']]);
            }
        } else {
            return $this->code(403)->error('非法请求');
        }
    }

//    /**
//     *  微信小程序统一登录接口（旧）
//     */
//    protected function miniappLogin()
//    {
//        if (request()->isPost()) {
//            $data = [
//                'code' => $this->request->param('code/s'),//换取用户信息需要的code
//                'user_info' => $this->request->param('user_info/s'), //小程序返回用户信息
//                'encrypted_data' => $this->request->param('encrypted_data/s'),//小程序授权返回的加密用户信息
//                'iv' => $this->request->param('iv/s'),//小程序授权返回的用户信息的解密iv
//                'signature' => $this->request->param('signature/s'),//参数校验签名
//                'official_uid' => $this->request->param('official_uid/s', ''),//绑定公众号的OPENID时候用的
//                'invite_code' => $this->request->param('invite_code/s', ''),//用户推荐码
//            ];
//            validate(Miniapp::class)->scene('login')->check($data);//如果验证器不是在应用下的自定义namespace 就是助手函数验证
//            $userInfo = json_decode(htmlspecialchars_decode($data['user_info']), true);//小程序返回用户信息
//            if (empty($userInfo)) {
//                return $this->code(403)->error('用户登录失败');
//            }
//            // 根据 JScode 获取 session
//            $miniapp = WechatProgram::isTypes($this->app_id)->auth->session($data['code']);//code换取个人授权信息
//            if (!empty($miniapp['errcode'])) {
//                return $this->code(403)->error('小程序授权失败', [], $miniapp['errcode']);
//            }
//            //获取(注册/登录)数据
//            $nickName = Inspect::filter_Emoji($userInfo['nickName']); //过滤emoji表情
//            $regdata['miniapp_uid'] = $miniapp['openid'];   //用户应用唯一标识
//            $regdata['session_key'] = $miniapp['session_key']; //小程序session_key
//            $regdata['official_uid'] = $data['official_uid']; //绑定公众号的OPENID时候用的
//            $regdata['unionid'] = empty($miniapp['unionid']) ? '' : $miniapp['unionid']; //用户公众平台下唯一标识
//            $regdata['nickname'] = $nickName ?? '微信-' . time(); //用户昵称
//            $regdata['avatar'] = $userInfo['avatarUrl']; //用户头像
//            $regdata['miniapp_id'] = $this->app_id;//MemberMiniapp表id
//            $regdata['invite_code'] = $data['invite_code'];  //推荐人的邀请码
//
//            //判断是登录还是注册
//            $uid = User::wechatReg($regdata);//注册新用户或者更新用户信息
//            if (!$uid) {
//                return $this->code(403)->error('用户认证失败！');
//            }
//            $userInfo = User::find($uid);//得到登录用户信息
//            //调用用户登录
//            $rs = UserService::loginUser($userInfo, 'mini_program', true);
//            if (!$rs['rs']) return $this->error($rs['error']);
//            //如果传了加密用户信息，则解密获取并绑定手机号
//            if ($data['iv'] && $data['encrypted_data']) {
//                try {
//                    //解密小程序信息，获取用户信息，得到手机号
//                    $decryptedData = WechatProgram::isTypes($this->app_id)->encryptor->decryptData($userInfo->session_key, $data['iv'], $data['encrypted_data']);
//                    if (!empty($decryptedData['purePhoneNumber'])) {
//                        $userInfo['mobile'] = $decryptedData['purePhoneNumber'];//绑定手机号
//                        $userInfo->save();
//                        $return_data['mobile'] = $decryptedData['purePhoneNumber'];
//                    }
//                } catch (\Exception $e) {
//                    return $this->error('绑定手机号失败：' . $e->getMessage());
//                }
//            }
//
//            $return_data = $rs['rs'];//登录成功token信息
//            $return_data['uid'] = $uid;  //用户信息
//            $return_data['invite_code'] = $userInfo['invite_code'];//获取小程序用户的邀请码
//            $return_data['session_id'] = get_session_id();//返回登录session
//            return $this->success('登录成功', $return_data);
//        } else {
//            return $this->error("miniappLogin not access");
//        }
//    }



    /**
     *  微信小程序统一登录接口
     */
    public function miniappLogin()
    {
        if (request()->isPost()) {
            $data = [
                'code' => $this->request->param('code/s'),//换取用户信息需要的code
                'user_info' => $this->request->param('user_info/s'), //小程序返回用户信息
                'encrypted_data' => $this->request->param('encrypted_data/s'),//小程序授权返回的加密用户信息
                'open_id' => '', //授权code
                'iv' => $this->request->param('iv/s'),//小程序授权返回的用户信息的解密iv
                'signature' => $this->request->param('signature/s'),//参数校验签名
                'official_uid' => $this->request->param('official_uid/s', ''),//绑定公众号的OPENID时候用的
                'invite_code' => $this->request->param('invite_code/s', ''),//用户推荐码
                'mobile' => '', //手机号
                'validate_code' => '', //验证码
            ];
            validate(Miniapp::class)->scene('login')->check($data);//如果验证器不是在应用下的自定义namespace 就是助手函数验证

            if (!$data['code']) {
                return $this->error('参数错误，关键参数不能为空');
            }

            $userInfo = json_decode(htmlspecialchars_decode($data['user_info']), true);//小程序返回用户信息
            if (empty($userInfo)) {
                return $this->code(403)->error('用户登录失败');
            }
            //获取小程序操作对象
            $app = WechatProgram::isTypes($this->app_id);
            if(!$app)return $this->error('未获取小程序授权');
                // 根据 JScode 获取 session
                $miniapp = $app->auth->session($data['code']);//code换取个人授权信息
                if (!empty($miniapp['errcode'])) {
                    return $this->code(403)->error('小程序授权失败', [], $miniapp['errcode']);
                }
            $regdata['mobile'] = $data['mobile'];
            //获取(注册/登录)数据
            $nickName = Inspect::filter_Emoji($userInfo['nickName']); //过滤emoji表情
            $regdata['miniapp_uid'] = $miniapp['openid'];   //用户应用唯一标识
            $regdata['session_key'] = $miniapp['session_key']; //小程序session_key
            $regdata['official_uid'] = $data['official_uid']; //绑定公众号的OPENID时候用的
            $regdata['unionid'] = empty($miniapp['unionid']) ? '' : $miniapp['unionid']; //用户公众平台下唯一标识
            $regdata['nickname'] = $nickName ?? '微信-' . time(); //用户昵称
            $regdata['avatar'] = $userInfo['avatarUrl']; //用户头像
            $regdata['miniapp_id'] = $this->app_id;//MemberMiniapp表id
            $regdata['invite_code'] = $data['invite_code'];  //推荐人的邀请码

            //如果传了加密用户信息，则解密获取并绑定手机号
            if ($data['iv'] && $data['encrypted_data']) {
                try {
                    //解密小程序信息，获取用户信息，得到手机号
                    $decryptedData = $app->encryptor->decryptData($regdata['session_key'], $data['iv'], $data['encrypted_data']);
                    if (!empty($decryptedData['purePhoneNumber'])) {
                        $regdata['mobile'] = $decryptedData['purePhoneNumber'];
                    }
                } catch (\Exception $e) {
                    return $this->error('绑定手机号失败：' . $e->getMessage());
                }
            }

//            if ($data['mobile']) {
//                //手机号验证码
//                if (!Sms::check($data['mobile'], $data['validate_code'], 'bind_mobile')) return $this->error('验证码错误');
//                $regdata['mobile'] = $data['mobile'];
//            }

            //判断是登录还是注册
            $uid = User::wechatReg($regdata,'mini_program');//注册新用户或者更新用户信息
            if (!$uid) {
                if (User::getErrorCode() == 400832) {

                    //缺少手机号需要重新变更手机号
                    $auth = [];
                    $auth_data = [];
                    $auth['open_id'] = $regdata['miniapp_uid'];
                    $auth['nickname'] = $nickName ?? 'WX-' . time();
                    $auth['avatar'] = $regdata['avatar'];
                    $auth['invite_code'] = $regdata['invite_code'];//后面添加推荐人用到
                    $auth_data['user_info'] = $auth;  //应用信息
                    $auth_data['type'] = 'mini_program';  //应用信息
                    return $this->code(200)->error(User::getError(), $auth_data, User::getErrorCode());
                } else {
                    return $this->code(200)->error('用户认证失败！');
                }
            }
            $userInfo = User::find($uid);//得到登录用户信息
            //调用用户登录
            $rs = UserService::loginUser($userInfo, 'mini_program', true);
            if (!$rs['rs']) return $this->error($rs['error']);
            if (isset($data['mobile'])&&$data['mobile']) Sms::clear($data['mobile'], 'bind_mobile');
            $return_data = $rs['rs'];//登录成功token信息
            $return_data['uid'] = $uid;  //用户信息
            $return_data['invite_code'] = $userInfo['invite_code'];//获取小程序用户的邀请码
            $return_data['session_id'] = get_session_id();//返回登录session
            $return_data['open_id'] =$regdata['miniapp_uid'];//返回登录session
            return $this->success('登录成功', $return_data);
        } else {
            return $this->error("miniappLogin not access");
        }
    }




    /**
     * 是否绑定手机号
     */
    public function haveBindMobile()
    {
        $data = [
            'code' => $this->request->param('code/s', ''),
        ];
        //判断是否开放平台应用(0是开发平台 1是独立应用)
        // 根据 JScode 获取 session
        $miniapp = WechatProgram::isTypes($this->app_id)->auth->session($data['code']);
        if (!empty($miniapp['errcode'])) {
            return $this->code(403)->error('小程序授权失败', [], $miniapp['errcode']);
        }
        $userInfo = User::where('member_miniapp_id', $this->app_id)->where('miniapp_uid', $miniapp['openid'])->find();
        $status = 0;//绑定状态默认未绑定
        $mobile = ''; //绑定手机号
        if (!$userInfo) return $this->success('查询成功', compact('status', 'mobile'));
        if ($userInfo) {
            $mobile = $userInfo['mobile'];
            if ($userInfo['mobile']) $status = 1;
        }
        return $this->success('查询成功', compact('status', 'mobile'));
    }


}